﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using ThingyCloud.Creatures.Properties;
using ThingyCloud.World;

namespace ThingyCloud.Creatures
{
	class Avatar : Creature
	{
		/// <summary>
		/// The list of all blobs that are in this avatar
		/// </summary>
		private List<Blob> Blobs { get; set; }

		/// <summary>
		/// Construct a new avatar! Blobs should be added manually
		/// </summary>
		public Avatar(List<Blob> blobs) : base()
		{
			Blobs = blobs;
			SetProperties(PropertiesManager.Instance.GetAvatarProperties(Weight));

			// Pick a random variant ID
			Random random = new Random(DateTime.Now.Millisecond);
			int idx = Math.Min(random.Next(0, Properties.Variants.Count), Properties.Variants.Count - 1);
			Variant = Properties.Variants[idx];
		}

		/// <summary>
		/// Publicly gets or privately sets the variant for this thingy
		/// </summary>
		public Variant Variant
		{
			get;
			private set;
		}

		/// <summary>
		/// Returns the weight of the avatar (=blobs.count)
		/// </summary>
		public int Weight
		{
			get
			{
				lock (Blobs)
				{
					return Blobs.Count;
				}
			}
		}

		/// <summary>
		/// Returns a COPY of the blobs list of this avatar
		/// </summary>
		public List<Blob> GetBlobs()
		{
			lock (Blobs)
			{
				return new List<Blob>(Blobs);
			}
		}

		/// <summary>
		/// Removes a blob from the list of blobs in this avatar
		/// </summary>
		public void RemoveBlob(Blob b)
		{
			lock (Blobs)
			{
				Blobs.Remove(b);
			}
		}

		/// <summary>
		/// Gets the complete bounding rectangle for this avatar. This includes all blobs.
		/// </summary>
		public Rectangle GetBoundingRect()
		{
			return GetBoundingRect(null);
		}

		/// <summary>
		/// Returns the total bounding rectangle of this avatar, where the supplied blob is ignored in the calculation. The
		/// argument can be null, in which case all blobs are used.
		/// </summary>
		public Rectangle GetBoundingRect(Blob exceptForBlob)
		{
			int x = int.MaxValue;
			int y = int.MaxValue;
			int width = int.MinValue;
			int height = int.MinValue;

			lock (Blobs)
			{
				foreach (Blob b in Blobs)
				{
					// Don't include this blob
					if (exceptForBlob != null && b == exceptForBlob)
						continue;

					Rectangle br = b.BoundingRect;
					x = Math.Min(br.X, x);
					y = Math.Min(br.Y, y);
				}

				foreach (Blob b in Blobs)
				{
					// Don't include this blob
					if (exceptForBlob != null && b == exceptForBlob)
						continue;

					Rectangle br = b.BoundingRect;
					width = Math.Max(width, ((br.X + br.Width) - x));
					height = Math.Max(height, ((br.Y + br.Height) - y));
				}
			}

			return new Rectangle(x, y, width, height);
		}

		/// <summary>
		/// This method checks whether the specified blob is part of this avatar
		/// </summary>
		/// <param name="b">The blob to check in here</param>
		/// <returns>Whether this avatar contains the supplied blob</returns>
		public bool ContainsBlob(Blob b)
		{
			lock (Blobs)
			{
				return Blobs.Contains(b);
			}
		}

		public override double X { get { return Globals.ToRelX(GetBoundingRect().X); } }
		public override double Y { get { return Globals.ToRelY(GetBoundingRect().Y); } }
		public int Width { get { return GetBoundingRect().Width; } }
		public int Height { get { return GetBoundingRect().Height; } }

		public override string ToString()
		{
			return string.Format(
					"Avatar: ID={0} Weight={1} X={2} Y={3} Width={4} Height={5}",
					ID,
					Weight,
					Globals.ToAbsX(X),
					Globals.ToAbsY(Y),
					Width,
					Height
					);
		}
	}
}
